package club.justwill.single.aspect;

import club.justwill.single.Controller.BaseController;
import club.justwill.single.Service.UserService;
import club.justwill.single.impl.ToolsImpl;
import club.justwill.single.model.CoreConstants;
import club.justwill.single.model.JsonResponse;
import club.justwill.single.persistence.document.SessionData;
import club.justwill.single.util.JsonResponseHelper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;

/**
 * Created by jaylon on 16-1-5.
 */
@Aspect
@Component
@Scope(WebApplicationContext.SCOPE_SESSION)
public class WebAspect extends BaseController implements Serializable {
    @Autowired
    private UserService userService;

    @Around("execution(public club.justwill.single.model.JsonResponse club.justwill.single.Controller.*Controller.*(..)) && @annotation(login)")
    @Order(50)
    public Object verifyLoginStatus(ProceedingJoinPoint pjp, LoginRequired login) throws Throwable {
        JsonResponse resp = new JsonResponse();
        if(!sessionState.isLoggedIn()) {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            if(request.getHeader("single") != null){
                SessionData data = userService.isLoginIn(request.getHeader("single"));
                return loginStatus(data,pjp,resp);
            } else if(!ToolsImpl.isEmpty(request.getCookies())) {
                Cookie[] cookies = request.getCookies();
                for(Cookie cookie : request.getCookies()) {
                    if("jsessionid".equals(cookie.getName())) {
                        try{
                            SessionData data = userService.isAppLogIn(cookie.getValue());
                            return loginStatus(data,pjp,resp);
                        } catch (Exception ex) {
                            resp.setFailed();
                            JsonResponseHelper.addError(resp, CoreConstants.USERID_CAST_ERROR);
                            return resp;
                        }
                    }
                }
            }
            resp.setFailed();
            JsonResponseHelper.addError(resp, CoreConstants.PLEASE_LOGIN);
            return resp;
        } else {
            return pjp.proceed();
        }
    }

    public Object loginStatus(SessionData data,ProceedingJoinPoint pjp,JsonResponse resp) throws Throwable {
        if(data != null) {
            sessionState.setUserId(data.getUserId());
            sessionState.setUserType(data.getUserType());
            sessionState.setSessionId(data.getSessionId());
            return pjp.proceed();
        } else {
            JsonResponseHelper.addError(resp, CoreConstants.PLEASE_LOGIN);
            resp.setFailed();
            return resp;
        }
    }
}